home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
dosrcss.zip
/
RCSFNMS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-18
|
35KB
|
1,036 lines
/*
* RCS file name handling
*/
#ifndef lint
static char
rcsid[]= "$Id: rcsfnms.c,v 5.5 90/07/16 21:30:57 lfk Release $ Purdue CS";
#endif
/****************************************************************************
* creation and deletion of semaphorefile,
* creation of temporary filenames and cleanup()
* pairing of RCS file names and working file names.
* Testprogram: define PAIRTEST
****************************************************************************
*/
/* Copyright (C) 1982, 1988, 1989 Walter Tichy
Distributed under license by the Free Software Foundation, Inc.
This file is part of RCS.
RCS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
RCS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RCS; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Report problems and direct all questions to:
rcs-bugs@cs.purdue.edu
*/
/* $Log: rcsfnms.c,v $
* Revision 5.5 90/07/16 21:30:57 lfk
* fixed a number of mistakes in the MKS/DOS filenaming stuff
*
* Revision 5.4 90/07/15 23:42:35 lfk
* Fixed one last '\\' versus '/' problem
*
* Revision 5.3 90/07/15 20:25:06 lfk
* Most major fixes added between rev 5.1 and rev 5.5:
* signals fixed so they work on MS-DOS
* Added MKS arguments code so argv can be large
* added code to handle slashes a'la Unix
* added more file extensions to system from MS-DOS
*
* Revision 5.2 90/07/15 11:33:42 ROOT_DOS
* DOS version of RCS 4.0 checked in for MODS
* by lfk@athena.mit.edu
* Also update to MSC 6.0
*
* revision 5.2 koya 90/01/24 10:22:39
* Change path-name handlars.
* Especially, separator of path names.
*
* revision 5.1 koya 90/01/24 07:05:43
* Initial revision
*
* Revision 4.8 89/05/01 15:09:41 narten
* changed getwd to not stat empty directories.
*
* Revision 4.7 88/11/08 12:01:22 narten
* changes from eggert@sm.unisys.com (Paul Eggert)
*
* Revision 4.7 88/08/09 19:12:53 eggert
* Fix troff macro comment leader bug; add Prolog; allow cc -R; remove lint.
*
* Revision 4.6 87/12/18 11:40:23 narten
* additional file types added from 4.3 BSD version, and SPARC assembler
* comment character added. Also, more lint cleanups. (Guy Harris)
*
* Revision 4.5 87/10/18 10:34:16 narten
* Updating version numbers. Changes relative to 1.1 actually relative
* to verion 4.3
*
* Revision 1.3 87/03/27 14:22:21 jenkins
* Port to suns
*
* Revision 1.2 85/06/26 07:34:28 svb
* Comment leader '% ' for '*.tex' files added.
*
* Revision 1.1 84/01/23 14:50:24 kcs
* Initial revision
*
* Revision 4.3 83/12/15 12:26:48 wft
* Added check for KDELIM in file names to pairfilenames().
*
* Revision 4.2 83/12/02 22:47:45 wft
* Added csh, red, and sl file name suffixes.
*
* Revision 4.1 83/05/11 16:23:39 wft
* Added initialization of Dbranch to InitAdmin(). Canged pairfilenames():
* 1. added copying of path from workfile to RCS file, if RCS file is omitted;
* 2. added getting the file status of RCS and working files;
* 3. added ignoring of directories.
*
* Revision 3.7 83/05/11 15:01:58 wft
* Added comtable[] which pairs file name suffixes with comment leaders;
* updated InitAdmin() accordingly.
*
* Revision 3.6 83/04/05 14:47:36 wft
* fixed Suffix in InitAdmin().
*
* Revision 3.5 83/01/17 18:01:04 wft
* Added getwd() and rename(); these can be removed by defining
* V4_2BSD, since they are not needed in 4.2 bsd.
* Changed sys/param.h to sys/types.h.
*
* Revision 3.4 82/12/08 21:55:20 wft
* removed unused variable.
*
* Revision 3.3 82/11/28 20:31:37 wft
* Changed mktempfile() to store the generated file names.
* Changed getfullRCSname() to store the file and pathname, and to
* delete leading "../" and "./".
*
* Revision 3.2 82/11/12 14:29:40 wft
* changed pairfilenames() to handle file.sfx,v; also deleted checkpathnosfx(),
* checksuffix(), checkfullpath(). Semaphore name generation updated.
* mktempfile() now checks for nil path; freefilename initialized properly.
* Added Suffix .h to InitAdmin. Added testprogram PAIRTEST.
* Moved rmsema, trysema, trydiraccess, getfullRCSname from rcsutil.c to here.
*
* Revision 3.1 82/10/18 14:51:28 wft
* InitAdmin() now initializes StrictLocks=STRICT_LOCKING (def. in rcsbase.h).
* renamed checkpath() to checkfullpath().
*/
#include "rcsbase.h"
#include <sys/types.h>
#include <sys/stat.h>
#ifdef MSDOS
#include <direct.h>
#else
#include <sys/dir.h>
#endif /* MSDOS */
extern char * rindex();
extern char * mktemp();
extern FILE * fopen();
extern char * getwd(); /* get working directory; forward decl */
extern int stat(), fstat();
extern FILE * finptr; /* RCS input file descriptor */
extern FILE * frewrite; /* New RCS file descriptor */
extern char * RCSfilename, * workfilename; /* filenames */
struct stat RCSstat, workstat; /* file status for RCS file and working file */
int haveRCSstat, haveworkstat; /* indicators if status availalble */
char tempfilename [NCPFN+10]; /* used for derived file names */
char sub1filename [NCPPN]; /* used for files path/file.sfx,v */
char sub2filename [NCPPN]; /* used for files path/RCS/file.sfx,v */
char semafilename [NCPPN]; /* name of semaphore file */
int madesema; /* indicates whether a semaphore file has been set */
char * tfnames[10]; /* temp. file names to be unlinked when finished */
int freefilename; /* index of next free file name in tfnames[] */
struct compair {
char * suffix, * comlead;
};
struct compair comtable[] = {
/* comtable pairs each filename suffix with a comment leader. The comment */
/* leader is placed before each line generated by the $Log keyword. This */
/* table is used to guess the proper comment leader from the working file's */
/* suffix during initial ci (see InitAdmin()). Comment leaders are needed */
/* for languages without multiline comments; for others they are optional. */
/* According to your MSDOS-environment, you change these settlements. !! */
/* If you can work on UN*X, it is worthwile to keep these. */
/* It however, may casue lack of memory on MSDOS */
/* $Author: lfk $ */
"", "# ", /* default for empty suffix */
"awk", "# ", /* AWK */
"c", " * ", /* C */
#ifdef ALL
"c++" "// " /* C++ */
"cc" "// " /* C++ */
"CC" "// " /* C++ */
"C" "// " /* C++ */
"cl", ";;; ", /* common lisp */
"csh", "# ", /* shell */
"e", "# ", /* efl */
"el", "; ", /* gnulisp */
#endif
"f", "c ", /* fortran */
"h", " * ", /* C-header */
"ksh", "# ", /* korn shell */
"l", " * ", /* lex NOTE: conflict between lex and franzlisp*/
"mac", "; ", /* macro vms or dec-20 or pdp-11 macro */
"me", ".\\\" ", /* me-macros t/nroff*/
#ifdef ALL
"ml", "; ", /* mocklisp */
#endif
"mm", ".\\\" ", /* mm-macros t/nroff*/
"ms", ".\\\" ", /* ms-macros t/nroff*/
#ifdef ALL
"p", " * ", /* pascal */
"perl", "# ", /* L. Wall's Perl */
"pl", "% ", /* prolog */
"r", "# ", /* ratfor */
"red", "% ", /* psl/rlisp */
"sh", "# ", /* shell */
"sl", "% ", /* psl */
#endif
"tex", "% ", /* tex */
"y", " * ", /* yacc */
#ifdef ALL
"ye", " * ", /* yacc-efl */
"yr", " * ", /* yacc-ratfor */
#endif
#ifdef sparc
"s", "! ", /* assembler */
#endif
#ifdef mc68000
"s", "| ", /* assembler */
#endif
#ifdef pdp11
"s", "/ ", /* assembler */
#endif
#ifdef vax
"s", "# ", /* assembler */
#endif
#ifdef MSDOS
"asm", "; ", /* assembler */
"bat", "REM ", /* MS-DOS command.com */
"cxx", "// ", /* MS-DOS c++ */
"fin", ".\\\" ", /* for *.fin files on MSDOS */
"fma", ".\\\" ", /* for fma-macors fin on MSDOS */
"for", "c ", /* MS Fortran */
"pl", "# ", /* L. Wall's Perl for MS-DOS */
#endif /* MSDOS */
nil, "" /* default for unknown suffix; must always be last */
};
ffclose(fptr)
FILE * fptr;
/* Function: checks ferror(fptr) and aborts the program if there were
* errors; otherwise closes fptr.
*/
{ if (ferror(fptr) || fclose(fptr)==EOF)
faterror("File read or write error; file system full?");
}
int trysema(RCSname,makesema)
char * RCSname; int makesema;
/* Function: Checks whether a semaphore file exists for RCSname. If yes,
* returns false. If not, creates one if makesema==true and returns true
* if successful. If a semaphore file was created, madesema is set to true.
* The name of the semaphore file is put into variable semafilename.
*/
{
#ifndef MSDOS
register char * tp, *sp, *lp;
int fdesc;
sp=RCSname;
lp = rindex(sp,'/');
if (lp==0) {
semafilename[0]='.'; semafilename[1]='/';
tp= &semafilename[2];
} else {
/* copy path */
tp=semafilename;
do *tp++ = *sp++; while (sp<=lp);
}
/*now insert `,' and append file name */
*tp++ = ',';
lp = rindex(sp, RCSSEP);
while (sp<lp) *tp++ = *sp++;
*tp++ = ','; *tp++ = '\0'; /* will be the same length as RCSname*/
madesema = false;
if (access(semafilename, 0) == 0) {
error("RCS file %s is in use",RCSname);
return false;
}
if (makesema) {
if ((fdesc=creat(semafilename, 000)) == -1) {
error("Can't create semaphore file for RCS file %s",RCSname);
return false;
} else
VOID close(fdesc);
madesema=true;
}
return true;
#else /* NOT MSDOS */
makesema = true;
return true;
#endif /* NOT MSDOS */
}
rmsema()
/* Function: delete the semaphore file if madeseam==true;
* sets madesema to false.
*/
{
#ifdef MSDOS
madesema = false ;
#else
if (madesema) {
madesema=false;
if (unlink(semafilename) == -1) {
error("Can't find semaphore file %s",semafilename);
}
}
#endif /* MSDOS */
}
InitCleanup()
{ freefilename = 0; /* initialize pointer */
}
cleanup()
/* Function: closes input file and rewrite file.
* Unlinks files in tfnames[], deletes semaphore file.
*/
{
register int i;
if (finptr!=NULL) VOID fclose(finptr);
if (frewrite!=NULL) VOID fclose(frewrite);
for (i=0; i<freefilename; i++) {
if (tfnames[i][0]!='\0') VOID unlink(tfnames[i]);
}
InitCleanup();
rmsema();
}
char * mktempfile(fullpath,filename)
register char * fullpath, * filename;
/* Function: Creates a unique filename using the process id and stores it
* into a free slot in tfnames. The filename consists of the path contained
* in fullpath concatenated with filename. filename should end in "XXXXXX".
* Because of storage in tfnames, cleanup() can unlink the file later.
* freefilename indicates the lowest unoccupied slot in tfnames.
* Returns a pointer to the filename created.
* Example use: mktempfile("/tmp/", somefilename)
*/
{
register char * lastslash, *tp;
if ((tp=tfnames[freefilename])==nil)
tp=tfnames[freefilename] = talloc(NCPPN);
#ifdef MSDOS
# ifdef MKS
if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
# else
if (fullpath!=nil && (lastslash=rindex(fullpath,'\\'))!=0) {
# endif
#else
if (fullpath!=nil && (lastslash=rindex(fullpath,'/'))!=0) {
#endif /* MSDOS */
/* copy path */
while (fullpath<=lastslash) *tp++ = *fullpath++;
}
while (*tp++ = *filename++);
return (mktemp(tfnames[freefilename++]));
}
char * bindex(sp,c)
register char * sp, c;
/* Function: Finds the last occurrence of character c in string sp
* and returns a pointer to the character just beyond it. If the
* character doesn't occur in the string, sp is returned.
*/
{ register char * r;
r = sp;
while (*sp) {
if (*sp++ == c) r=sp;
}
return r;
}
InitAdmin()
/* function: initializes an admin node */
{ register char * Suffix;
register int i;
Head=Dbranch=nil; AccessList=nil; Symbols=nil; Locks=nil;
StrictLocks=STRICT_LOCKING;
/* guess the comment leader from the suffix*/
Suffix=bindex(workfilename, '.');
#ifdef MSDOS
Suffix = strlwr( Suffix );
#endif /* MSDOS */
if (Suffix==workfilename) Suffix= ""; /* empty suffix; will get default*/
for (i=0;;i++) {
if (comtable[i].suffix==nil) {
Comment=comtable[i].comlead; /*default*/
break;
} elsif (strcmp(Suffix,comtable[i].suffix)==0) {
Comment=comtable[i].comlead; /*default*/
break;
}
}
Lexinit(); /* Note: if finptr==NULL, reads nothing; only initializes*/
}
char * findpairfile(argc, argv, fname)
int argc; char * argv[], *fname;
/* Function: Given a filename fname, findpairfile scans argv for a pathname
* ending in fname. If found, returns a pointer to the pathname, and sets
* the corresponding pointer in argv to nil. Otherwise returns fname.
* argc indicates the number of entries in argv. Some of them may be nil.
*/
{
register char * * next, * match;
register int count;
for (next = argv, count = argc; count>0; next++,count--) {
#ifdef MSDOS
# ifdef MKS
if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
# else
if ((*next != nil) && strcmp(bindex(*next,'\\'),fname)==0) {
# endif
#else
if ((*next != nil) && strcmp(bindex(*next,'/'),fname)==0) {
#endif /* MSDOS */
/* bindex finds the beginning of the file name stem */
match= *next;
*next=nil;
return match;
}
}
return fname;
}
int pairfilenames(argc, argv, mustread, tostdout)
int argc; char ** argv; int mustread, tostdout;
/* Function: Pairs the filenames pointed to by argv; argc indicates
* how many there are.
* Places a pointer to the RCS filename into RCSfilename,
* and a pointer to the name of the working file into workfilename.
* If both the workfilename and the RCS filename are given, and tostdout
* is true, a warning is printed.
*
* If the working file exists, places its status into workstat and
* sets haveworkstat to 0; otherwise, haveworkstat is set to -1;
* Similarly for the RCS file and the variables RCSstat and haveRCSstat.
*
* If the RCS file exists, it is opened for reading, the file pointer
* is placed into finptr, and the admin-node is read in; returns 1.
* If the RCS file does not exist and mustread==true, an error is printed
* and 0 returned.
* If the RCS file does not exist and mustread==false, the admin node
* is initialized to empty (Head, AccessList, Locks, Symbols, StrictLocks, Dbranch)
* and -1 returned.
*
* 0 is returned on all errors. Files that are directories are errors.
* Also calls InitCleanup();
*/
{
register char * sp, * tp;
char * lastsep, * purefname, * pureRCSname;
int opened, returncode;
#ifdef MSDOS
struct stat dirstat;
#endif /* MSDOS */
char * RCS1;
char prefdir[NCPPN];
if (*argv == nil) return 0; /* already paired filename */
if (rindex(*argv,KDELIM)!=0) {
/* KDELIM causes havoc in keyword expansion */
error("RCS file name may not contain %c",KDELIM);
return 0;
}
InitCleanup();
/* first check suffix to see whether it is an RCS file or not */
#ifdef MSDOS
# ifdef MKS
purefname=bindex(*argv, '/'); /* skip path */
# else
purefname=bindex(*argv, '\\'); /* skip path */
# endif
#else
purefname=bindex(*argv, '/'); /* skip path */
#endif /* MSDOS */
#ifdef MSDOS
# ifdef MKS
if( ( pureRCSname = strstr( *argv, "rcs/" ) ) != NULL){
#else
if( ( pureRCSname = strstr( *argv, "RCS\\" ) ) != NULL){
#endif
/* RCS file name given*/
RCS1 = (*argv);
/* derive workfilename*/
sp = purefname; tp=tempfilename;
while( *sp != '\0' ) *tp++=*sp++; *tp= '\0';
workfilename=findpairfile(argc-1,argv+1,tempfilename);
if( strlen(pureRCSname) > NCPFN + 4 ) {
/* To avoid, ambiguous file name. eg."RCS\RCS\foo.c" */
if( strlen(pureRCSname + 4) != (int) NULL ){
error("file name %s is ambiguous", RCS1);
return 0;
}
error("RCS file name %s too long",RCS1);
return 0;
}
} else {
/* working file given; now try to find RCS file */
workfilename=*argv;
/* derive RCS file name*/
# ifdef MKS
strcpy( tempfilename, "rcs/" );
# else
strcpy( tempfilename, "RCS\\" );
# endif
strcat( tempfilename, purefname );
RCS1=findpairfile(argc-1,argv+1,tempfilename);
# ifdef MKS
pureRCSname = strstr( RCS1, "rcs/" );
# else
pureRCSname = strstr( RCS1, "RCS\\" );
# endif
if (strlen(pureRCSname)>NCPFN+4) {
error("working file name %s too long",workfilename);
return 0;
}
}
# ifdef MKS
if( strchr( workfilename, '/' ) != NULL ){
# else
if( strchr( workfilename, '\\' ) != NULL ){
# endif
error("Sorry, file name %s confuse RCS", workfilename );
return 0;
}
#else /* MSDOS */
lastsep=rindex(purefname, RCSSEP);
if (lastsep!= 0 && *(lastsep+1)==RCSSUF && *(lastsep+2)=='\0') {
/* RCS file name given*/
RCS1=(*argv); pureRCSname=purefname;
/* derive workfilename*/
sp = purefname; tp=tempfilename;
while (sp<lastsep) *tp++ = *sp++; *tp='\0';
/* try to find workfile name among arguments */
workfilename=findpairfile(argc-1,argv+1,tempfilename);
if (strlen(pureRCSname)>NCPFN) {
error("RCS file name %s too long",RCS1);
return 0;
}
} else {
/* working file given; now try to find RCS file */
workfilename= *argv;
/* derive RCS file name*/
sp=purefname; tp=tempfilename;
while (*tp++ = *sp++);
*(tp-1)=RCSSEP; *tp++=RCSSUF; *tp++='\0';
/* Try to find RCS file name among arguments*/
RCS1=findpairfile(argc-1,argv+1,tempfilename);
pureRCSname=bindex(RCS1, '/');
if (strlen(pureRCSname)>NCPFN) {
error("working file name %s too long",workfilename);
return 0;
}
}
#endif /* MSDOS */
/* now we have a (tentative) RCS filename in RCS1 and workfilename */
/* First, get status of workfilename */
haveworkstat=stat(workfilename, &workstat);
if ((haveworkstat==0) && ((workstat.st_mode & S_IFDIR) == S_IFDIR)) {
diagnose("Directory %s ignored",workfilename);
return 0;
}
/* Second, try to find the right RCS file */
#ifdef MSDOS
RCSfilename=pureRCSname;
if (pureRCSname != RCS1){
error("Sorry, file name %s confuse RCS", RCS1);
return 0;
}else{
opened = ( ( finptr=fopen(pureRCSname, "r" ) ) != NULL );
if(opened){
returncode = 1;
}else{
if (mustread) {
error("Can't find %s",RCSfilename);
return 0;
}else{
if( stat("RCS", &dirstat) == -1 ){
error("Can't find RCS subdirectory");
return 0;
}else{
if( !( dirstat.st_mode & S_IFDIR ) ){
error("RCS is really directory?");
return 0;
}else returncode = -1;
}
}
}
}
#else /* MSDOS */
if (pureRCSname!=RCS1) {
/* a path for RCSfile is given; single RCS file to look for */
finptr=fopen(RCSfilename=RCS1, "r");
if (finptr!=NULL) {
returncode=1;
} else { /* could not open */
if (access(RCSfilename,0)==0) {
error("Can't open existing %s", RCSfilename);
return 0;
}
if (mustread) {
error("Can't find %s", RCSfilename);
return 0;
} else {
/* initialize if not mustread */
returncode = -1;
}
}
} else {
/* no path for RCS file name. Prefix it with path of work */
/* file if RCS file omitted. Make a second name including */
/* RCSDIR and try to open that one first. */
sub1filename[0]=sub2filename[0]= '\0';
if (RCS1==tempfilename) {
/* RCS file name not given; prepend work path */
sp= *argv; tp= sub1filename;
while (sp<purefname) *tp++ = *sp ++;
*tp='\0';
VOID strcpy(sub2filename,sub1filename); /* second one */
}
VOID strcat(sub1filename,RCSDIR);
VOID strcpy(prefdir,sub1filename); /* preferred directory for RCS file*/
VOID strcat(sub1filename,RCS1); VOID strcat(sub2filename,RCS1);
opened=(
((finptr=fopen(RCSfilename=sub1filename, "r"))!=NULL) ||
((finptr=fopen(RCSfilename=sub2filename,"r"))!=NULL) );
if (opened) {
/* open succeeded */
returncode=1;
} else {
/* open failed; may be read protected */
if ((access(RCSfilename=sub1filename,0)==0) ||
(access(RCSfilename=sub2filename,0)==0)) {
error("Can't open existing %s",RCSfilename);
return 0;
}
if (mustread) {
error("Can't find %s nor %s",sub1filename,sub2filename);
return 0;
} else {
/* initialize new file. Put into ./RCS if possible, strip off suffix*/
RCSfilename= (access(prefdir,0)==0)?sub1filename:sub2filename;
returncode= -1;
}
}
}
#endif /* MSDOS */
if (returncode == 1) { /* RCS file open */
haveRCSstat=fstat(fileno(finptr),&RCSstat);
if ((haveRCSstat== 0) && ((RCSstat.st_mode & S_IFDIR) == S_IFDIR)) {
diagnose("Directory %s ignored",RCSfilename);
return 0;
}
Lexinit(); getadmin();
} else { /* returncode == -1; RCS file nonexisting */
haveRCSstat = -1;
InitAdmin();
};
if (tostdout&&
!(RCS1==tempfilename||workfilename==tempfilename))
/*The last term determines whether a pair of */
/* file names was given in the argument list */
warn("Option -p is set; ignoring output file %s",workfilename);
return returncode;
}
char * getfullRCSname()
/* Function: returns a pointer to the full path name of the RCS file.
* Calls getwd(), but only once.
* removes leading "../" and "./".
*/
{ static char pathbuf[NCPPN];
static char namebuf[NCPPN];
static int pathlength;
register char * realname, * lastpathchar;
register int dotdotcounter, realpathlength;
#ifdef MSDOS
/* Treat a full path name containing the drive name */
/* Added by $Author: lfk $ */
# ifdef MKS
if (RCSfilename[1] == ':' && RCSfilename[2] == '/') {
# else
if (RCSfilename[1] == ':' && RCSfilename[2] == '\\') {
# endif
#else
if (*RCSfilename=='/') {
#endif /* MSDOS */
return(RCSfilename);
} else {
if (pathlength==0) { /*call curdir for the first time*/
if (getwd(pathbuf)==NULL)
faterror("Can't build current directory path");
pathlength=strlen(pathbuf);
#ifdef MSDOS
/* Generally, a MSDOS path name seems to be like "A:\" */
/* Added by $Author: lfk $ */
# ifdef MKS
if (!((pathlength==3) && (pathbuf[2]=='/'))) {
pathbuf[pathlength++]='/';
# else
if (!((pathlength==3) && (pathbuf[2]=='\\'))) {
pathbuf[pathlength++]='\\';
# endif
/* Check needed because some getwd implementations */
/* generate "/" for the root. */
}
#else
if (!((pathlength==1) && (pathbuf[0]=='/'))) {
pathbuf[pathlength++]='/';
/* Check needed because some getwd implementations */
/* generate "/" for the root. */
}
#endif /* MSDOS */
}
/*the following must be redone since RCSfilename may change*/
/* find how many ../ to remvove from RCSfilename */
dotdotcounter =0;
realname = RCSfilename;
#ifdef MSDOS /* Chaged '/' to '\\' : By $Author: lfk $ */
while( realname[0]=='.' &&
# ifdef MKS
(realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
if (realname[1]=='/') {
# else
(realname[1]=='\\'||(realname[1]=='.'&&realname[2]=='\\'))){
if (realname[1]=='\\') {
# endif
/* drop leading ./ */
realname += 2;
} else {
/* drop leading ../ and remember */
dotdotcounter++;
realname += 3;
}
}
#else
while( realname[0]=='.' &&
(realname[1]=='/'||(realname[1]=='.'&&realname[2]=='/'))){
if (realname[1]=='/') {
/* drop leading ./ */
realname += 2;
} else {
/* drop leading ../ and remember */
dotdotcounter++;
realname += 3;
}
}
#endif /* MSDOS */
/* now remove dotdotcounter trailing directories from pathbuf*/
lastpathchar=pathbuf + pathlength-1;
while (dotdotcounter>0 && lastpathchar>pathbuf) {
/* move pointer backwards over trailing directory */
lastpathchar--;
#ifdef MSDOS
# ifdef MKS
if (*lastpathchar=='/') {
# else
if (*lastpathchar=='\\') {
# endif
#else
if (*lastpathchar=='/') {
#endif /* MSDOS */
dotdotcounter--;
}
}
if (dotdotcounter>0) {
error("Can't generate full path name for RCS file");
return RCSfilename;
} else {
/* build full path name */
realpathlength=lastpathchar-pathbuf+1;
VOID strncpy(namebuf,pathbuf,realpathlength);
VOID strcpy(&namebuf[realpathlength],realname);
return(namebuf);
}
}
}
/* In MSDOS and (perhaps) OS/2, any directries are writable. */
/* So, the below check is NON-SENSE !! : $Author: lfk $ */
int trydiraccess(filename)
char * filename;
/* checks write permission in directory of filename and returns
* true if writable, false otherwise
*/
{
char pathname[NCPPN];
register char * tp, *sp, *lp;
#ifdef MSDOS
return true;
#else
lp = rindex(filename,'/');
if (lp==0) {
/* check current directory */
if (access(".",2)==0)
return true;
else {
error("Current directory not writable");
return false;
}
}
/* copy path */
sp=filename;
tp=pathname;
do *tp++ = *sp++; while (sp<=lp);
*tp='\0';
if (access(pathname,2)==0)
return true;
else {
error("Directory %s not writable", pathname);
return false;
}
#endif /* MSDOS */
}
#ifndef V4_2BSD
/* rename() and getwd() will be provided in bsd 4.2 */
#ifndef MSDOS
int rename(from, to)
char * from, *to;
/* Function: renames a file with the name given by from to the name given by to.
* unlinks the to-file if it already exists. returns -1 on error, 0 otherwise.
*/
{ VOID unlink(to); /* no need to check return code; will be caught by link*/
/* no harm done if file "to" does not exist */
if (link(from,to)<0) return -1;
return(unlink(from));
}
#define dot "."
#define dotdot ".."
char * getwd(name)
char * name;
/* Function: places full pathname of current working directory into name and
* returns name on success, NULL on failure.
* getwd is an adaptation of pwd. May not return to the current directory on
* failure.
*/
{
FILE *file;
struct stat d, dd;
char buf[2]; /* to NUL-terminate dir.d_name */
struct direct dir;
int rdev, rino;
int off;
register i,j;
name[off= 0] = '/';
name[1] = '\0';
buf[0] = '\0';
if (stat("/", &d)<0) return NULL;
rdev = d.st_dev;
rino = d.st_ino;
for (;;) {
if (stat(dot, &d)<0) return NULL;
if (d.st_ino==rino && d.st_dev==rdev) {
if (name[off] == '/') name[off] = '\0';
chdir(name); /*change back to current directory*/
return name;
}
if ((file = fopen(dotdot,"r")) == NULL) return NULL;
if (fstat(fileno(file), &dd)<0) goto fail;
chdir(dotdot);
if(d.st_dev == dd.st_dev) {
if(d.st_ino == dd.st_ino) {
if (name[off] == '/') name[off] = '\0';
chdir(name); /*change back to current directory*/
VOID fclose(file);
return name;
}
do {
if (fread((char *)&dir, sizeof(dir), 1, file) !=1)
goto fail;
} while (dir.d_ino != d.st_ino);
}
else do {
if(fread((char *)&dir, sizeof(dir), 1, file) != 1) {
goto fail;
}
if (dir.d_ino == 0)
dd.st_ino = d.st_ino + 1;
else if (stat(dir.d_name, &dd) < 0)
goto fail;
} while(dd.st_ino != d.st_ino || dd.st_dev != d.st_dev);
VOID fclose(file);
/* concatenate file name */
i = -1;
while (dir.d_name[++i] != 0);
for(j=off+1; j>0; --j)
name[j+i+1] = name[j];
off=i+off+1;
name[i+1] = '/';
for(--i; i>=0; --i)
name[i+1] = dir.d_name[i];
} /* end for */
fail: VOID fclose(file);
return NULL;
}
#else /* MSDOS */
char *getwd(name)
char *name;
{
int a,i;
(void)getcwd(name, NCPPN);
#ifdef MKS
strlwr(name);
a = strlen(name);
for ( i = 0; i <= a; i++)
if(name[i] == '\\')
name[i] = '/';
#endif
return name;
}
#endif /* MSODS */
#endif
#ifdef MSDOS
char *gettmpdir()
{
char tp[NCPPN];
strcpy( tp, (char *) getenv("TMP") );
if( *tp == (char) NULL ) strcpy( tp, "." );
if( tp[strlen(tp) - 1] != '\\' )
strcat( tp, "\\" );
return tp;
}
#endif /* MSDOS */
#ifdef PAIRTEST
/* test program for pairfilenames() and getfullRCSname() */
char * workfilename, *RCSfilename;
extern int quietflag;
main(argc, argv)
int argc; char *argv[];
{
int result;
int initflag,tostdout;
quietflag=tostdout=initflag=false;
cmdid="pair";
while(--argc, ++argv, argc>=1 && ((*argv)[0] == '-')) {
switch ((*argv)[1]) {
case 'p': tostdout=true;
break;
case 'i': initflag=true;
break;
case 'q': quietflag=true;
break;
default: error("unknown option: %s", *argv);
break;
}
}
do {
RCSfilename=workfilename=nil;
result=pairfilenames(argc,argv,!initflag,tostdout);
if (result!=0) {
diagnose("RCSfile: %s; working file: %s",RCSfilename,workfilename);
diagnose("Full RCS file name: %s", getfullRCSname());
}
switch (result) {
case 0: continue; /* already paired file */
case 1: if (initflag) {
error("RCS file %s exists already",RCSfilename);
} else {
diagnose("RCS file %s exists",RCSfilename);
}
VOID fclose(finptr);
break;
case -1:diagnose("RCS file does not exist");
break;
}
} while (++argv, --argc>=1);
}
#endif